/**
 * 接口拦截
 */

import type { PlasmoCSConfig } from "plasmo"

import emitter from "@/contents/interception/interfaces"

console.table(Object.fromEntries(emitter.all))

const rewriteJSONP = ((originalCreateElement) => {
  document.createElement = function (tagName) {
    if (tagName.toLowerCase() !== "script") return originalCreateElement.call(document, tagName)
    const script = originalCreateElement.call(document, tagName)
    const descriptor = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, "src")
    Object.defineProperty(script, "src", {
      ...descriptor,
      set: function (value) {
        const interfaces = Object.keys(Object.fromEntries(emitter.all)).map((name) => name.trim())
        const targetName = value.match(/\&api=([^&]+)/)?.at(1)
        const name = targetName?.trim()
        if (!name || !interfaces.includes(name)) return descriptor.set.call(this, value)
        const reg = /\bcallback=([^&]+)/i
        const callbackName = value.match(reg)?.at(1) || ""
        const modifiedUrl = value.replace(reg, `&callback=custom_${callbackName}`)
        // 设置新回调函数
        window[`custom_${callbackName}`] = (data) => {
          emitter.emit(name, { data, name })
          window[callbackName as keyof Window](data) // 调用原始回调
        }
        return descriptor.set.call(this, modifiedUrl)
      }
    })
    return script
  }
})(document.createElement)

const rewriteXHR = ((originalXHROpen, originalXHRSend) => {
  XMLHttpRequest.prototype.open = async function (method, url) {
    const interfaces = Object.keys(Object.fromEntries(emitter.all)).map((name) => name.trim())
    this._name = url.match(/\&api=([^&]+)/)?.at(1) || url
    this._isTarget = interfaces.includes(this._name)
    return originalXHROpen.apply(this, arguments)
  }
  XMLHttpRequest.prototype.send = function (body) {
    const xhr = this
    const originalReadyStateChange = xhr.onreadystatechange
    const originalLoad = xhr.onload
    const modifyData = async () => {
      const originalResponse = xhr.response
      const data = JSON.parse(originalResponse)
      emitter.emit(xhr._name, { data, name: xhr._name })
      const modifiedResponse = JSON.stringify(data)
      Object.defineProperty(xhr, "response", { value: modifiedResponse })
      Object.defineProperty(xhr, "responseText", { value: modifiedResponse })
    }
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr._isTarget) modifyData()
      originalReadyStateChange && originalReadyStateChange.apply(xhr, arguments)
    }
    xhr.onload = function () {
      if (xhr._isTarget) modifyData()
      originalLoad && originalLoad.apply(xhr, arguments)
    }
    originalXHRSend.call(xhr, body)
  }
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)

export const config: PlasmoCSConfig = {
  matches: ["https://s.taobao.com/search*"],
  all_frames: true,
  run_at: "document_start",
  world: "MAIN"
}
